<script setup lang="ts">
import { computed, h, reactive, shallowRef, watch } from 'vue';
import type { TreeOption } from 'naive-ui';
import { $t } from '@/locales';
import { fetchGetMenuTree, fetchGetRoleCheckedMenuIds, fetchSaveRoleMenuIds } from '@/service/api';
import SvgIcon from '@/components/custom/svg-icon.vue';

defineOptions({
  name: 'MenuAuthModal'
});
interface Props {
  roleId: string;
}
const props = defineProps<Props>();
const title = computed(() => $t('common.edit') + $t('page.manage.role.menuAuth'));
const visible = defineModel<boolean>('visible', {
  default: false
});

const menuTree = shallowRef<TreeOption[]>([]);
const checks = shallowRef<string[]>([]);
const pageSelectOptions = shallowRef<CommonType.Option[]>([]);
const model: Api.SystemManage.RoleMenu = reactive(createDefaultModel());

function updateHome(val: string) {
  model.homePage = val;
}
function createDefaultModel() {
  return {
    id: props.roleId,
    menuIds: [],
    homePage: 'home'
  };
}

async function handleSubmit() {
  model.menuIds = checks.value;
  const { error, data: result } = await fetchSaveRoleMenuIds(model);
  if (!error && result) {
    window.$message?.success?.($t('common.modifySuccess'));
    closeModal();
  }
}
function closeModal() {
  visible.value = false;
}

/**
 * 递归生成树结构
 *
 * @param item 菜单数据
 * @returns 树结构
 */
function recursive(item: Api.SystemManage.Menu): TreeOption {
  const treeItem: TreeOption = {
    key: item.id,
    label: item.i18nKey ? $t(item.i18nKey as App.I18n.I18nKey) : item.menuName,
    prefix: () => {
      const icon = item.iconType === '1' ? item.icon : `#${item.icon}`;
      const localIcon = item.iconType === '2' ? item.icon : undefined;
      return h(SvgIcon, {
        icon,
        localIcon,
        class: 'text-icon'
      });
    }
  };
  if (item.children) {
    treeItem.children = item.children.map(recursive);
  }
  return treeItem;
}

/**
 * 树结构扁平化且只保留菜单
 *
 * @param item 菜单数据
 * @param flatMenuList 集合
 */
function flattenMenu(item: Api.SystemManage.Menu, flatMenuList: Api.SystemManage.Menu[]) {
  if (item.menuType === '2') {
    flatMenuList.push(item);
  }
  if (item.children && item.children.length > 0) {
    item.children.map(item2 => flattenMenu(item2, flatMenuList));
  }
}

async function getMenuTree() {
  const { error, data } = await fetchGetMenuTree();
  if (!error) {
    menuTree.value = data?.map(item => recursive(item));

    const result: Api.SystemManage.Menu[] = [];
    data?.map(item => flattenMenu(item, result));
    pageSelectOptions.value = result?.map(item => ({
      label: item.i18nKey ? $t(item.i18nKey as App.I18n.I18nKey) : item.menuName,
      value: item.routeName
    }));
  }
}
async function getCheckMenuIds() {
  const { error, data } = await fetchGetRoleCheckedMenuIds(props.roleId);
  if (!error) {
    checks.value = data;
    getMenuTree();
  }
}
function handleInit() {
  if (props.roleId) {
    Object.assign(model, createDefaultModel());
    getCheckMenuIds();
  }
}

watch(visible, () => {
  if (visible.value) {
    handleInit();
  }
});
</script>

<template>
  <NModal v-model:show="visible" :title="title" preset="card" class="w-480px">
    <div class="mb-12px flex-y-center gap-16px">
      <NText class="text-gray-500">{{ $t('page.manage.menu.home') }}</NText>
      <NSelect
        class="w-160px"
        size="small"
        :value="model.homePage"
        :options="pageSelectOptions"
        :placeholder="$t('page.manage.menu.form.home')"
        @update:value="updateHome"
      />
    </div>
    <NTree
      v-model:checked-keys="checks"
      :show-line="true"
      :data="menuTree"
      block-line
      expand-on-click
      checkable
      cascade
      virtual-scroll
      height="320px"
    />
    <template #footer>
      <NSpace justify="end" :size="16">
        <NButton @click="closeModal">{{ $t('common.cancel') }}</NButton>
        <NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
      </NSpace>
    </template>
  </NModal>
</template>

<style scoped></style>
